package com.zhb.zhbojbackendquestionservice.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionChoice;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionRequest;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessage;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessageRole;
import com.volcengine.ark.runtime.service.ArkService;

import com.zhb.zhbojbackendcommon.common.ErrorCode;
import com.zhb.zhbojbackendcommon.exception.BusinessException;
import com.zhb.zhbojbackendmodel.model.codesandbox.JudgeInfo;
import com.zhb.zhbojbackendmodel.model.dto.question.JudgeCase;
import com.zhb.zhbojbackendmodel.model.dto.questionsubmit.QuestionSubmitAddRequest;
import com.zhb.zhbojbackendmodel.model.entity.Question;
import com.zhb.zhbojbackendmodel.model.entity.QuestionSubmit;
import com.zhb.zhbojbackendmodel.model.entity.User;
import com.zhb.zhbojbackendmodel.model.enums.JudgeInfoMessageEnum;
import com.zhb.zhbojbackendmodel.model.enums.QuestionSubmitLanguageEnum;
import com.zhb.zhbojbackendmodel.model.enums.QuestionSubmitStatusEnum;
import com.zhb.zhbojbackendmodel.model.vo.AiQuestionVO;
import com.zhb.zhbojbackendquestionservice.service.QuestionService;
import com.zhb.zhbojbackendquestionservice.service.QuestionSubmitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 通用的 AI 调用类
 */
@Service
@Slf4j
public class AIManager {

    @Resource
    private ArkService aiService;

    @Resource
    private QuestionService questionService;
    @Resource
    private QuestionSubmitService questionSubmitService;
    private final String DEFAULT_MODEL = "deepseek-v3-241226";

    /**
     * 调用 AI 接口，获取响应字符串
     *
     * @param userPrompt
     * @return
     */
    public String doChat(String userPrompt) {
        return doChat("", userPrompt, DEFAULT_MODEL);
    }

    /**
     * 调用 AI 接口，获取响应字符串
     *
     * @param systemPrompt
     * @param userPrompt
     * @return
     */
    public String doChat(String systemPrompt, String userPrompt) {
        return doChat(systemPrompt, userPrompt, DEFAULT_MODEL);
    }

    /**
     * 调用 AI 接口，获取响应字符串
     *
     * @param systemPrompt
     * @param userPrompt
     * @param model
     * @return
     */
    public String doChat(String systemPrompt, String userPrompt, String model) {
        // 构造消息列表
        final List<ChatMessage> messages = new ArrayList<>();
        final ChatMessage systemMessage = ChatMessage.builder().role(ChatMessageRole.SYSTEM).content(systemPrompt).build();
        final ChatMessage userMessage = ChatMessage.builder().role(ChatMessageRole.USER).content(userPrompt).build();
        messages.add(systemMessage);
        messages.add(userMessage);
        // 构造请求
        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                //                .model("deepseek-v3-241226")
                .model(model)
                .messages(messages)
                .build();
        // 调用接口发送请求
        List<ChatCompletionChoice> choices = aiService.createChatCompletion(chatCompletionRequest).getChoices();
        if (CollUtil.isNotEmpty(choices)) {
            return (String) choices.get(0).getMessage().getContent();
        }
        throw new BusinessException(ErrorCode.OPERATION_ERROR, "AI 调用失败，没有返回结果");
        //        // shutdown service after all requests is finished
        //        aiService.shutdownExecutor();
    }


    public static final String AIJudge = "现在你是一位精通OJ竞赛题目的算法专家，接下来我会按照以下固定格式给你发送内容：\n" +
            "用户代码：\n" +
            "{用户提交的代码}\n" +
            "输出用例:\n" +
            "{该算法题的输入用例}\n" +
            "请认真根据上面给你的内容给出输出用例，只需要输出用例，不需要其他的信息\n";
    public static final String PRECONDITION = "现在你是一位精通OJ竞赛题目的算法专家，接下来我会按照以下固定格式给你发送内容：\n" +
            "题目标题：\n" +
            "{该算法题的标题}\n" +
            "题目内容:\n" +
            "{该算法题的具体内容}\n" +
            "题目使用语言:\n" +
            "{解决该题目所使用的编程语言}\n" +
            "请认真根据这两部分内容，必须严格按照以下指定格式生成markdown内容（此外不要输出任何多余的开头、结尾、注释）\n" +
            "【【【【【\n" +
            "明确的代码分析，越详细越好，不要生成多余的注释(详细说明如何处理args输入及算法逻辑)\n" +
            "【【【【【\n" +
            "解答该题目对应的代码，主类必须是Main，代码相关参数是通过args命令行传来的且写在main方法(完成输入转换)中，只需生成要求编程语言的代码\n";
    /**
     * 获取 AI 生成结果
     *
     * @param
     * @param title
     * @param content
     * @return
     */
    public AiQuestionVO getGenResultByDeepSeek(final String title, final String content, final String language, final Long questionId) {
        String promote = AIManager.PRECONDITION + "标题 " + title + " \n内容: " + content + "\n编程语言: " + language;
        String resultData = doChat(promote);
        log.info("AI 生成的信息: {}", resultData);
        String genResult = null;
        String genCode = resultData;
        if (resultData.split("【【【【【").length >= 3) {
            genResult =resultData.split("【【【【【")[1].trim();;
            genCode = resultData.split("【【【【【")[2].trim();
        }
        return new AiQuestionVO(genResult, genCode, questionId);
    }

    /**
     * AI判题
     * @param questionSubmitAddRequest
     * @param loginUser
     * @return
     */
    public long doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest, User loginUser) {
        // 校验编程语言是否合法
        String language = questionSubmitAddRequest.getLanguage();
        QuestionSubmitLanguageEnum languageEnum = QuestionSubmitLanguageEnum.getEnumByValue(language);
        if (languageEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "编程语言错误");
        }
        //获取到用户提交的代码
        String code = questionSubmitAddRequest.getCode();
        long questionId = questionSubmitAddRequest.getQuestionId();
        // 判断实体是否存在，根据类别获取实体
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 是否已提交题目
        long userId = loginUser.getId();
        //获取题目的输出用例
        String questionJudgeCase = question.getJudgeCase();
        List<JudgeCase> judgeCases1 = JSONUtil.toList(questionJudgeCase, JudgeCase.class);
        List<String> judgeOutput = judgeCases1.stream().map(JudgeCase::getOutput).collect(Collectors.toList());
        // 每个用户串行提交题目
        QuestionSubmit questionSubmit = new QuestionSubmit();
        questionSubmit.setUserId(userId);
        questionSubmit.setQuestionId(questionId);
        questionSubmit.setCode(code);
        questionSubmit.setLanguage(language);
        Question question1 = new Question();
        question1.setId(questionId);
        int currentNum=question.getSubmitNum()==null?0:question.getSubmitNum();
        question1.setSubmitNum(currentNum+1);
        questionService.updateById(question1);
        // 设置初始状态
        questionSubmit.setStatus(QuestionSubmitStatusEnum.WAITING.getValue());
        questionSubmit.setJudgeInfo("{}");
        boolean save = questionSubmitService.save(questionSubmit);
        if (!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据插入失败");
        }
        Long questionSubmitId = questionSubmit.getId();
        //执行AI判题
        String judgeCase = question.getJudgeCase();
        List<JudgeCase> judgeCaseList = JSONUtil.toList(judgeCase, JudgeCase.class);
        List<String> inputList = judgeCaseList.stream().map(JudgeCase::getInput).collect(Collectors.toList());
        String promote = AIManager.AIJudge + "用户代码 " + code  + "\n输入用例: " + inputList;
        String resultData = doChat(promote);
        log.info("AI 生成的信息: {}", resultData);
//        String resultDataJsonStr="["+resultData+"]";
//        JSONArray jsonArray = JSONUtil.parseArray(resultDataJsonStr);
        // 将 resultData 按换行符分隔成字符串数组
        String[] resultDataArray = resultData.split("\n");

// 创建 JudgeCase 对象列表，每个数字作为 output
        List<JudgeCase> judgeCases = Arrays.stream(resultDataArray)
                .map(String::trim)  // 去除空格
                .map(num -> {
                    JudgeCase judgeCase1 = new JudgeCase();
                    judgeCase1.setOutput(num);  // 将每个数字设置为 output
                    return judgeCase1;
                })
                .collect(Collectors.toList());

// 获取 output 列表
        List<String> judgeCaseListOutput = judgeCases.stream()
                .map(JudgeCase::getOutput)
                .collect(Collectors.toList());

        log.info("JudgeCase 输出: {}", judgeCaseListOutput);
        JudgeInfoMessageEnum judgeInfoMessageEnum = JudgeInfoMessageEnum.ACCEPTED;
        JudgeInfo judgeInfo = new JudgeInfo();
        //判断AI判题的输出用例和题目的输出用例适数量是否相等
//        List<JudgeCase> judgeCases = JSONUtil.toList(jsonArray, JudgeCase.class);
//        List<String> judgeCaseListOutput = judgeCases.stream().map(JudgeCase::getOutput).collect(Collectors.toList());
        if (judgeCaseListOutput.size()!=judgeOutput.size()){
            judgeInfoMessageEnum=JudgeInfoMessageEnum.WRONG_ANSWER;
            judgeInfo.setMessage(judgeInfoMessageEnum.getValue());
        }
        // 依次判断每一项输出和预期输出是否相等
        for (int i = 0; i < judgeCaseListOutput.size(); i++) {
            String result = judgeCaseListOutput.get(i);
            if (!result.equals(judgeOutput.get(i))) {
                judgeInfoMessageEnum = JudgeInfoMessageEnum.WRONG_ANSWER;
                judgeInfo.setMessage(judgeInfoMessageEnum.getValue());
            }
        }
        judgeInfo.setMessage(judgeInfoMessageEnum.getValue());
        // 修改数据库中的判题结果
        QuestionSubmit submitresult = new QuestionSubmit();
        submitresult.setId(questionSubmitId);
        submitresult.setStatus(QuestionSubmitStatusEnum.SUCCEED.getValue());
        submitresult.setJudgeInfo(JSONUtil.toJsonStr(judgeInfo));
        boolean updateById = questionSubmitService.updateById(submitresult);
        if (!updateById) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "题目更新错误");
        }
        //修改数据库中题目的信息
        Question questionresult = new Question();
        questionresult.setId(questionId);
        int currentNumresult=questionresult.getAcceptedNum()==null?0:question.getAcceptedNum();
        questionresult.setAcceptedNum(currentNumresult+1);
        Boolean updateQuestionById = questionService.updateById(questionresult);
        if (!updateQuestionById) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "题目状态更新错误");
        }
        return questionSubmitId;
    }
}